package com.ticket.sass.common.rpc.keepalive

import com.ticket.sass.common.rpc.dto.input.keepalive.SendInput
import com.ticket.sass.common.rpc.dto.output.ResultWrapOutput
import com.ticket.sass.common.rpc.exceptions.ApiStatusException
import org.springframework.beans.factory.annotation.Value
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Component
import org.springframework.web.reactive.function.client.*
import reactor.core.publisher.Mono


/**
 * @author 朱其鹏
 * @date 2024/3/24 15:51
 */
@Component("keepalive.client")
class Client {
    @Value("\${keepalive.server-url}")
    private lateinit var serverUrl: String

    /**
     * 构建 web 请求
     */
    private fun buildClient(): WebClient {
        return WebClient.builder()
            .filter(ExchangeFilterFunction.ofResponseProcessor {
                if (it.statusCode() != HttpStatus.OK) {
                    throw ApiStatusException(it.statusCode().value().toString(), it.statusCode().name)
                }
                Mono.just(it)
            })
            .baseUrl(serverUrl)
            .build()
    }

    /**
     * 发送消息
     */
    fun send(
        input: SendInput,
        subscribe: ((ResultWrapOutput<Any>) -> Unit)? = null
    ) : Mono<ResultWrapOutput<Any>> {
        return post("/send", input)
            .bodyToMono<ResultWrapOutput<Any>>()
            .also { mono ->
                subscribe?.also { mono.subscribe(it) }
            }
    }

    /**
     * POST 请求
     *
     * @param path      请求路径
     * @param input     请求参数
     */
    private fun post(
        path: String,
        input: Any,
    ) : WebClient.ResponseSpec {
        return buildClient()
            .post()
            .uri { it.path(path).build() }
            .bodyValue(input)
            .retrieve()
    }
}
